<script setup lang="ts">
import {
    isSelecting,
    startPos,
    currentPos,
    handleMouseDown,
    handleMouseEnter,
    handleMouseUp,
} from "./mouseSelection";
import { ref, reactive, watch } from "vue";
const textVal = ref("");
interface GridConfig {
    size: number;
    threshold: number;
    detectionMode: "luminance" | "color";
}
interface MergeArea {
    id: string; // 合并区域的唯一 ID
    cells: Array<{ x: number; y: number }>; // 合并的单元格坐标
}

const props = defineProps<{
    maxGridSize?: number;
}>();

const emit = defineEmits<{
    (e: "gridUpdate", grid: string[][]): void;
}>();

// 响应式状态
const imagePreview = ref<string>("");
const gridData = ref<string[]>([]);
const config = reactive<GridConfig>({
    size: 8,
    threshold: 128,
    detectionMode: "luminance",
});
let tpmSize = ref(config.size)

const mode  = ref<"merge">("");


const mergedAreas = reactive<MergeArea[]>([]); // 存储所有合并区域

const getXY= (index: number,size: number )=>{
    return {x: Math.floor(index / size), y: index % size}
}
const changeSize = () => {
    const oldSize = tpmSize.value;
    const newSize = config.size
    if (oldSize === newSize || !newSize || !oldSize) return
    // 创建新网格容器
    const newGrid = Array(newSize*newSize).fill('')

    // 计算新旧中心点坐标
    const oldCenter = (oldSize - 1) / 2
    const newCenter = (newSize - 1) / 2
    const distance = oldCenter - newCenter
    
   gridData.value.map((item:string,index )=> {
        if (!item) return
        //根据index 和oldSize 计算坐标
        const {x,y} = getXY(index,oldSize)
        const newX = x - distance
        const newY = y - distance
        newGrid[newX * newSize + newY ] = item
    })
    gridData.value = newGrid
    tpmSize.value = newSize
    emit('gridUpdate', gridData.value)

};

// 文件处理
const handleFileSelect = (e: Event) => {
    const file = (e.target as HTMLInputElement).files?.[0];
    if (!file) return;
    imagePreview.value = URL.createObjectURL(file);
};

// 核心处理逻辑
const processImage = async () => {
    if (!imagePreview.value) return changeSize();
    

    try {
        let imageData =null
        if(imagePreview.value){
             const img = await createImageBitmap(
                await fetch(imagePreview.value).then((r) => r.blob())
            );
            const canvas = new OffscreenCanvas(img.width, img.height);
            const ctx = canvas.getContext("2d")!;

            ctx.drawImage(img, 0, 0);
            imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
             gridData.value = analyzePixels(imageData,config.size);
            
        }
       
       
        tpmSize.value = config.size
        emit("gridUpdate", gridData.value);
       
       
    } catch (error) {
        console.error("图片处理失败:", error);
    }
};
const getRandom = () => {
    return Math.random().toString(36).slice(-8);
};
// 优化亮度计算方法
const calculateCellLuminance = (
    imageData: ImageData,
    startX: number,
    startY: number,
    size: number
): number => {
    let total = 0;
    let count = 0;
    
    for (let y = startY; y < startY + size; y++) {
        for (let x = startX; x < startX + size; x++) {
            const idx = (y * imageData.width + x) * 4;
            const r = imageData.data[idx];
            const g = imageData.data[idx + 1];
            const b = imageData.data[idx + 2];
            total += 0.299 * r + 0.587 * g + 0.114 * b;
            count++;
        }
    }
    return count > 0 ? total / count : 0;
};
// 新增响应式数据
const tileImages = ref([]);
// 像素分析
const analyzePixels = (imageData: ImageData, gridSize: number): string[] => {
    
   const grid: string[] = [];
    const cellSize = imageData.width / gridSize;
    
    for (let x = 0; x < gridSize; x++) {
        for (let y = 0; y < gridSize; y++) {
            const luminance = calculateCellLuminance(
                imageData,
                y * cellSize,
                x * cellSize,
                cellSize
            );
            grid[y * gridSize + x] = luminance > config.threshold ? getRandom() : "";
        }
    }
    return grid;
};
// todo  拆分的顺序都不对
const imageDivide = async () => {
    if(!imagePreview.value)return
    const img = await createImageBitmap(await fetch(imagePreview.value).then(r => r.blob()));
     const canvas = new OffscreenCanvas(img.width, img.height);
    const ctx = canvas.getContext("2d")!;

    ctx.drawImage(img, 0, 0);
    const cellSizex = img.width / tpmSize.value;
    const cellSizey = img.height / tpmSize.value;
    tileImages.value = []; // 清空旧数据
    for(let i = 0; i < gridData.value.length; i++){
        const {x,y} = getXY(i,tpmSize.value)
         const tileCanvas = new OffscreenCanvas(cellSizex, cellSizey);
            const tileCtx = tileCanvas.getContext('2d')!;
            tileCtx.drawImage(
                img,
                (x+1 )* cellSizex,
                (y+1)* cellSizey,
                cellSizex,
                cellSizey,
                0,
                0,
                cellSizex,
                cellSizey
            )
            console.log((x+1 )* cellSizex,(y+1)* cellSizey)
             // 转换为DataURL存储
            const blob = await tileCanvas.convertToBlob();
            tileImages.value[i] =URL.createObjectURL(blob);
    }
    
}


const resetGridData = () => {
    gridData.value = Array(config.size * config.size).fill("")
};
resetGridData()

const onClick = (cell,index) => {
    if(cell){
        gridData.value[index] = ""
        gridInfo.value[cell] = {}
    }else{ 
        gridData.value[index] = getRandom()
    }
};
const beforeHandleMouseDown = (index) => {
    const {x,y} = getXY(index,config.size)
    handleMouseDown(x,y)
};
const beforeHandleMouseEnter = (index) => {
    const {x,y} = getXY(index,config.size)
    handleMouseEnter(x,y)
};
const beforeHandleMouseUp = () => {
    handleMouseUp((minX, minY, maxX, maxY) => {
        const selectedCells: Array<{ x: number; y: number }> = []; // 选中的单元格坐标
        const mergeId = `merge-${getRandom()}`; // 生成唯一的合并 ID
        // 创建新数组保证响应式更新
        const newGrid = gridData.value.map(row => row)

        // 批量更新选中区域
        for (let y = minY; y <= maxY; y++) {
            for (let x = minX; x <= maxX; x++) {
                newGrid[x*tpmSize.value+y] = mode.value === 'merge'?mergeId: getRandom()
                if( mode.value === 'merge'){
                    selectedCells.push({ x, y }); // 记录选中的单元格坐标
                }
            }
        }
        if( mode.value === 'merge'){
            // 存储合并区域信息
            mergedAreas.push({
                id: mergeId,
                cells: selectedCells,
            });
        }
       


        gridData.value = newGrid
        emit('gridUpdate', gridData.value)
    })
};
const isCellSelected = (index): boolean => {
    const {x,y} = getXY(index,tpmSize.value)
    if (!isSelecting.value) return false;

    const minX = Math.min(startPos.x, currentPos.x);
    const maxX = Math.max(startPos.x, currentPos.x);
    const minY = Math.min(startPos.y, currentPos.y);
    const maxY = Math.max(startPos.y, currentPos.y);

    return x >= minX && x <= maxX && y >= minY && y <= maxY;
};
const gridInfo: any = ref({})

let curIndex = 0
const insertGrid = () => {
    gridInfo.value = {}
    curIndex = 0
    const arr = textVal.value.split('\n').filter(item => item)
    for (let i = 0; i < gridData.value.length; i++) {
        if (gridData.value[i] && arr[curIndex]) {
            gridInfo.value[gridData.value[i]].text = arr[curIndex]
            curIndex++
        }
    }
}
// 实现函数
const shuffleObjectValues = <T extends Record<string, any>>(obj: T): T => {
    // 获取值数组并洗牌
    const values = Object.values(obj)
    for (let i = values.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [values[i], values[j]] = [values[j], values[i]];
    }

    // 重建对象
    return Object.keys(obj).reduce((acc, key, index) => {
        acc[key as keyof T] = values[index];
        return acc;
    }, {} as T);
}

const shuffleGridInfo = () => {
    gridInfo.value = shuffleObjectValues(gridInfo.value)
}
const changeMode = () => {
    mode.value=mode.value==='merge'?'':'merge'
}
const splitArrayIntoGroups = (arr: any[], groupSize: number): any[][] => {
    const result = [];
    for (let i = 0; i < arr.length; i += groupSize) {
        result.push(arr.slice(i, i + groupSize));
    }
    return result;
};

const getGridAreas = ()=>{
    const result = splitArrayIntoGroups( gridData.value,tpmSize.value)
    let arr = []
    result.forEach((item,x) => {
        let tpmArr = []
        item.forEach((cell,y) => {
            tpmArr.push(cell?cell:('A'+(x*tpmSize.value+y)))
        });
        arr.push(`"${tpmArr.join(' ')}"`)
    });
    return arr.join('\n');

}


const tearing = ref(false);

const startTear = () => {
  tearing.value = true;
};


// 加绘画 黑白画布

</script>

<template>
    <div class="scanner-container">
        <div class="controls">
            <input type="file" accept="image/*" @change="handleFileSelect" />
            <div class="config-group">
                <label>
                    网格密度：
                    <input type="number" v-model.number="config.size" :min="2" :max="props.maxGridSize || 20" />
                </label>
                <label>
                    敏感度阈值：
                    <input type="range" v-model.number="config.threshold" min="0" max="255" />
                    {{ config.threshold }}
                </label>
            </div>
            <button @click="processImage">生成网格</button>
            <button @click="imageDivide">按图片分割生成</button>
            

        </div>
        <div>
            <textarea v-model="textVal"></textarea>
            <button @click="insertGrid">填入格子</button>
            <button @click="shuffleGridInfo">随机调换值</button>
        </div>
        <div>
            <button @click="changeMode">{{mode==='merge'?'退出合并':'合并模式'}}</button>
        </div>

        <img v-if="imagePreview" :src="imagePreview" class="preview-image" />

        <div class="grid-container" :style="{
            gridTemplateColumns: `repeat(${tpmSize}, 1fr)`,
            gridTemplateRows: `repeat(${tpmSize}, 80px)`,
            'grid-template-areas':getGridAreas()
        }"
        >
            <div v-for="(cell, y) in gridData" :key="cell||y" class="grid-cell"
            :style="{gridArea: cell||('A'+y)}"
            :class="{active: cell,selecting:isCellSelected(y),merged : mergedAreas.some(area => area.id===cell)}"
            @click="onClick(cell,y)" 
            @mousedown="beforeHandleMouseDown( y)" 
            @mousemove="beforeHandleMouseEnter( y)"
            @mouseup="beforeHandleMouseUp"
            >{{ gridInfo[cell]?.text || '' }}
                <div v-show="cell||mergedAreas.some(area => area.id===cell) ||tileImages[y]">
                    <div class="flip-container">
                        <div class="flip-image">
                            <img :src="tileImages[y]" alt="示例图片">
                        </div>
                    </div>
                </div>
           
            </div>
        </div>
       
    </div>
</template>
<style scoped>
.scanner {
    max-width: 800px;
    margin: 20px auto;
    padding: 20px;
    font-family: system-ui;
}

.controls {
    display: flex;
    gap: 12px;
    margin-bottom: 20px;
}

input[type="file"] {
    border: 2px dashed #ccc;
    padding: 8px;
}

button {
    background: #2196f3;
    color: white;
    border: none;
    padding: 8px 16px;
    border-radius: 4px;
    cursor: pointer;
    transition: opacity 0.2s;
}

button:hover {
    opacity: 0.8;
}

.grid-container {
    display: grid;
    gap: 2px;
    background: white;
    padding: 8px;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.grid-cell {
    width: 100%;
    background: #f5f5f5;
    transition: background 0.3s ease, transform 0.2s ease;
    /* 
     *  禁止文本选择  出现选一次可以亮起，选第二次就不可以，没想到这个导致怀疑半天
     */
    -webkit-user-select: none;
}

.grid-cell.active {
    background: #e6d1d3;
}

#image-preview {
    max-width: 100%;
    margin: 20px 0;
    border-radius: 4px;
}

.grid-cell.selecting {
    box-shadow: 0 0 0 2px #2196f3;
    z-index: 1;
}

.grid-cell.selecting.active {
    box-shadow: 0 0 0 2px #2196f3, inset 0 0 8px rgba(33, 150, 243, 0.4);
}
.grid-cell.merged {
    background: #ff9800; /* 合并区域背景颜色 */
    border: 2px solid #ff5722; /* 合并区域边框 */
}
.selection-preview {
    position: absolute;
    background: rgba(33, 150, 243, 0.1);
    border: 2px dashed #2196f3;
    pointer-events: none;
    transition: all 0.1s;
}


.flip-container {
    perspective: 1000px; /* 设置3D透视效果 */
    width: 100%;
    height: 80px;
}

.flip-image {
    width: 100%;
    height: 100%;
    position: relative;
    transform-style: preserve-3d; /* 保持3D空间 */
    transition: transform 0.6s ease; /* 添加过渡动画 */
    transform-origin: top center; /* 设置翻转的基点 */
    clip-path: polygon(
        0% 0%,
        100% 0%,
        100% 100%,
        0% 100%
    );
}

.flip-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.flip-container:hover .flip-image {
    transform: rotateX(90deg); /* 鼠标悬停时沿X轴旋转90度 */
        clip-path: ellipse(75% 80% at 50% 20%);
}



</style>